Data Preparation

Top Companies Prep

Bring top companies into dataframe.

#names(cmspayments)
#Companies is "Submitting_Applicable_Manufacturer_or_Applicable_GPO_Name"
toppayor <- aggregate(Total_Amount_of_Payment_USDollars ~ Submitting_Applicable_Manufacturer_or_Applicable_GPO_Name
                                                        
                      ,cmspayments,FUN = sum)
colnames(toppayor) <- c("Company","TotalPayment")
toppayor <- head(toppayor[order(toppayor$TotalPayment, decreasing= TRUE),], n = 10)
names(cmspayments)
 [1] "X"                                                                 "Change_Type"                                                       "Covered_Recipient_Type"                                           
 [4] "Teaching_Hospital_CCN"                                             "Teaching_Hospital_ID"                                              "Teaching_Hospital_Name"                                           
 [7] "Physician_Profile_ID"                                              "Physician_First_Name"                                              "Physician_Middle_Name"                                            
[10] "Physician_Last_Name"                                               "Physician_Name_Suffix"                                             "Recipient_Primary_Business_Street_Address_Line1"                  
[13] "Recipient_Primary_Business_Street_Address_Line2"                   "Recipient_City"                                                    "Recipient_State"                                                  
[16] "Recipient_Zip_Code"                                                "Recipient_Country"                                                 "Recipient_Province"                                               
[19] "Recipient_Postal_Code"                                             "Physician_Primary_Type"                                            "Physician_Specialty"                                              
[22] "Physician_License_State_code1"                                     "Physician_License_State_code2"                                     "Physician_License_State_code3"                                    
[25] "Physician_License_State_code4"                                     "Physician_License_State_code5"                                     "Submitting_Applicable_Manufacturer_or_Applicable_GPO_Name"        
[28] "Applicable_Manufacturer_or_Applicable_GPO_Making_Payment_ID"       "Applicable_Manufacturer_or_Applicable_GPO_Making_Payment_Name"     "Applicable_Manufacturer_or_Applicable_GPO_Making_Payment_State"   
[31] "Applicable_Manufacturer_or_Applicable_GPO_Making_Payment_Country"  "Total_Amount_of_Payment_USDollars"                                 "Date_of_Payment"                                                  
[34] "Number_of_Payments_Included_in_Total_Amount"                       "Form_of_Payment_or_Transfer_of_Value"                              "Nature_of_Payment_or_Transfer_of_Value"                           
[37] "City_of_Travel"                                                    "State_of_Travel"                                                   "Country_of_Travel"                                                
[40] "Physician_Ownership_Indicator"                                     "Third_Party_Payment_Recipient_Indicator"                           "Name_of_Third_Party_Entity_Receiving_Payment_or_Transfer_of_Value"
[43] "Charity_Indicator"                                                 "Third_Party_Equals_Covered_Recipient_Indicator"                    "Contextual_Information"                                           
[46] "Delay_in_Publication_Indicator"                                    "Record_ID"                                                         "Dispute_Status_for_Publication"                                   
[49] "Product_Indicator"                                                 "Name_of_Associated_Covered_Drug_or_Biological1"                    "Name_of_Associated_Covered_Drug_or_Biological2"                   
[52] "Name_of_Associated_Covered_Drug_or_Biological3"                    "Name_of_Associated_Covered_Drug_or_Biological4"                    "Name_of_Associated_Covered_Drug_or_Biological5"                   
[55] "NDC_of_Associated_Covered_Drug_or_Biological1"                     "NDC_of_Associated_Covered_Drug_or_Biological2"                     "NDC_of_Associated_Covered_Drug_or_Biological3"                    
[58] "NDC_of_Associated_Covered_Drug_or_Biological4"                     "NDC_of_Associated_Covered_Drug_or_Biological5"                     "Name_of_Associated_Covered_Device_or_Medical_Supply1"             
[61] "Name_of_Associated_Covered_Device_or_Medical_Supply2"              "Name_of_Associated_Covered_Device_or_Medical_Supply3"              "Name_of_Associated_Covered_Device_or_Medical_Supply4"             
[64] "Name_of_Associated_Covered_Device_or_Medical_Supply5"              "Program_Year"                                                      "Payment_Publication_Date"                                         
[67] "PhysSpcOne"                                                        "PhysSpcTwo"                                                        "PhysSpcThree"                                                     

Simplify the data manipulation

Using RSQLite, use SQL to simplify data manipulation.

Using the top companies dataframe, write to table.

rsqlcon <- dbConnect(RSQLite::SQLite(), ":memory:")

dbWriteTable(conn = rsqlcon
             ,"cmspaytable"
             ,cmspayments
             ,overwrite = TRUE)

topCompany <- RSQLite::dbGetQuery(conn = rsqlcon
                                ,"select Submitting_Applicable_Manufacturer_or_Applicable_GPO_Name as Company
                                        ,sum(Total_Amount_of_Payment_USDollars) as TotalPayments
                                  from cmspaytable
                                  group by 1
                                  order by 2 desc
                                  limit 10"
                                  )
##has top company by revenue
dbWriteTable(conn = rsqlcon
             ,"topcompanytable"
             ,topCompany
             ,overwrite = TRUE)
print(topCompany)

Create a dataset with company, payment specialty, and total payments. Group by the attributes and sum the measures. Then get the top companies with specialty only if they exist in the top 10 companies data frame.

topspecialty <- RSQLite::dbGetQuery(conn = rsqlcon
                    , "select c.Submitting_Applicable_Manufacturer_or_Applicable_GPO_Name as Company
                             ,c.Physician_Specialty
                             ,sum(c.Total_Amount_of_Payment_USDollars) as TotalPayments
                       from cmspaytable as c inner join (select distinct Company
                                          from topcompanytable
                                          order by topcompanytable.TotalPayments desc
                                          limit 5
                                          ) as tt on c.Submitting_Applicable_Manufacturer_or_Applicable_GPO_Name
                                                   = tt.Company
                       group by 1,2
                       order by 3 desc,2,1
                    ")
topspecialty$Physician_Specialty <- within(topspecialty, X <- ifelse(nchar(topspecialty$Physician_Specialty) == "0"
                                                          , "NA"
                                                          ,topspecialty$Physician_Specialty)
                                          )
                      
print(topspecialty)

Visualize

  1. Top 10 companies barchart
  2. Top 5 companies

#plot_ly(x = c(topCompany$Company)
#       ,y = c(topCompany$TotalPayments)
#       ,type = "bar")
#par(mfrow - c(2,2))
g <- ggplot(topCompany,aes(Company,TotalPayments/1000000))
g+geom_bar(stat = "identity"
           ,colour = "dark blue"
           ,fill = "dodger blue") +theme(axis.text.x = element_text(angle=45
                                                                ,hjust = 1)
                                     ,axis.text.y = element_text(angle = 45)
                                     )+ labs(y = "Total Payments")+geom_line()+
                geom_hline(yintercept = mean(topCompany$TotalPayments/1000000), color="blue")
summa

### use ping to produce image and control size.
specialtytree <- file.path(getwd(),paste("specialtytreemap",".png",sep = ""))
png(filename = specialtytree,
    width = 1000, height = 850, units = "px", pointsize = 12,
    bg = "white",  res = NA,## ...,
    ##type = c("cairo", "cairo-png", "Xlib", "quartz"), 
    antialias = c("default")
)



treemap::treemap(dtf = topspecialty, index = c("Company","Physician_Specialty")
                 ,type = "index"
                 , fontsize.labels=c(12,10,10)
                 ,vSize = "TotalPayments"
                 ,vColor = "Physician_Specialty"
                 ,command.line.output = FALSE
                 #,fontface.labels = "bold"
                 ,palette = "Set1"
                 ,fun.aggregate = "sum"
                 , align.labels=list(
                                      c("center", "center"), 
                                      c("center", "bottom")
                                      )
                  )
dev.off()
Specialty Tree Map

Specialty Tree Map

LS0tCnRpdGxlOiAiQ29tcGxpYW5jZSBBbmFseXRpY3MgT3BlbiBQYXltZW50cyBDYXNlICIKYXV0aG9yOiAiTWljaGFlbCBHYXJjaWEiCmRhdGU6ICJNYXkgMjgsIDIwMTkiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgd29yZF9kb2N1bWVudDogZGVmYXVsdAotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYAoKYGBge3IgbG9hZHBrZywgaW5jbHVkZT1UUlVFLGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkoUlNRTGl0ZSkKbGlicmFyeShEQkkpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKI2xpYnJhcnkocGxvdGx5KQpgYGAKCiMjIERhdGEgUHJlcGFyYXRpb24KCmBgYHtyIGZldGNoZGF0YSwgaW5jbHVkZT1UUlVFLGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmN3ZCA8LSBwYXN0ZTAoZ2V0d2QoKSkKc2V0d2QoY3dkKQoKZG93bmxvYWQuZmlsZSh1cmwgPSAiaHR0cHM6Ly9zMy5hbWF6b25hd3MuY29tL2lzdHJlZXQtYXNzZXRzL2kwamhzel9VZGlfWmwyanhKLWMtcFEvQ01TX09QRU5fUEFZTUVOVFNfREVDXzIwMTMuemlwIgogICAgICAgICAgICAgICxkZXN0ZmlsZSA9ICJDTVNfT1BFTl9QQVlNRU5UU19ERUNfMjAxMy56aXAiKQoKCmNtc3ppcCA8LSB1bnppcCgiQ01TX09QRU5fUEFZTUVOVFNfREVDXzIwMTMuemlwIikKY21zcGF5bWVudHMgPC0gcmVhZC5jc3YoY21zemlwKQojIyMgcGh5c2ljaWFuIHNwZWNpYWx0eSBoYXMgbmFzCmNtc3BheW1lbnRzJFBoeXNpY2lhbl9TcGVjaWFsdHkgPC0gIGFzLmNoYXJhY3RlcihjbXNwYXltZW50cyRQaHlzaWNpYW5fU3BlY2lhbHR5KQpjbXNwYXltZW50cyRQaHlzaWNpYW5fU3BlY2lhbHR5IDwtIGlmZWxzZShuY2hhcihjbXNwYXltZW50cyRQaHlzaWNpYW5fU3BlY2lhbHR5KT09IDAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCAiTkEiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxjbXNwYXltZW50cyRQaHlzaWNpYW5fU3BlY2lhbHR5KQpgYGAKCgojIyMgVG9wIENvbXBhbmllcyBQcmVwCkJyaW5nIHRvcCBjb21wYW5pZXMgaW50byBkYXRhZnJhbWUuCgpgYGB7ciB0b3BwYXllciwgZWNobz1UUlVFLGluY2x1ZGU9VFJVRX0KI25hbWVzKGNtc3BheW1lbnRzKQojQ29tcGFuaWVzIGlzICJTdWJtaXR0aW5nX0FwcGxpY2FibGVfTWFudWZhY3R1cmVyX29yX0FwcGxpY2FibGVfR1BPX05hbWUiCnRvcHBheW9yIDwtIGFnZ3JlZ2F0ZShUb3RhbF9BbW91bnRfb2ZfUGF5bWVudF9VU0RvbGxhcnMgfiBTdWJtaXR0aW5nX0FwcGxpY2FibGVfTWFudWZhY3R1cmVyX29yX0FwcGxpY2FibGVfR1BPX05hbWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICxjbXNwYXltZW50cyxGVU4gPSBzdW0pCmNvbG5hbWVzKHRvcHBheW9yKSA8LSBjKCJDb21wYW55IiwiVG90YWxQYXltZW50IikKdG9wcGF5b3IgPC0gaGVhZCh0b3BwYXlvcltvcmRlcih0b3BwYXlvciRUb3RhbFBheW1lbnQsIGRlY3JlYXNpbmc9IFRSVUUpLF0sIG4gPSAxMCkKYGBgCgoKYGBge3IgcGh5c3NwZWNpYWxfc3BsaXQsZWNobz1UUlVFLCBpbmNsdWRlPVRSVUV9Cgojd2l0aGluKGNtc3BheW1lbnRzLCBGT088LWRhdGEuZnJhbWUoZG8uY2FsbCgncmJpbmQnLCBzdHJzcGxpdChhcy5jaGFyYWN0ZXIoY21zcGF5bWVudHMkUGh5c2ljaWFuX1NwZWNpYWx0eSksICd8JywgZml4ZWQ9VFJVRSkpKSkKcGh5c3BsaXQgPC0gZGF0YS5mcmFtZShkby5jYWxsKCdyYmluZCcsIHN0cnNwbGl0KGFzLmNoYXJhY3RlcihjbXNwYXltZW50cyRQaHlzaWNpYW5fU3BlY2lhbHR5KSwnfCcsZml4ZWQ9VFJVRSkpKQpjb2xuYW1lcyhwaHlzcGxpdCkgPC0gYygiUGh5c1NwY09uZSIsIlBoeXNTcGNUd28iLCJQaHlzU3BjVGhyZWUiKQoKYGBgCgoKIyMjIFNpbXBsaWZ5IHRoZSBkYXRhIG1hbmlwdWxhdGlvbgpVc2luZyBSU1FMaXRlLCB1c2UgU1FMIHRvIHNpbXBsaWZ5IGRhdGEgbWFuaXB1bGF0aW9uLgoKVXNpbmcgdGhlIHRvcCBjb21wYW5pZXMgZGF0YWZyYW1lLCB3cml0ZSB0byB0YWJsZS4gCmBgYHtyIHNxbHRyYW5zZm9ybSwgZWNobz1UUlVFLCBpbmNsdWRlPVRSVUV9CnJzcWxjb24gPC0gZGJDb25uZWN0KFJTUUxpdGU6OlNRTGl0ZSgpLCAiOm1lbW9yeToiKQoKZGJXcml0ZVRhYmxlKGNvbm4gPSByc3FsY29uCiAgICAgICAgICAgICAsImNtc3BheXRhYmxlIgogICAgICAgICAgICAgLGNtc3BheW1lbnRzCiAgICAgICAgICAgICAsb3ZlcndyaXRlID0gVFJVRSkKCnRvcENvbXBhbnkgPC0gUlNRTGl0ZTo6ZGJHZXRRdWVyeShjb25uID0gcnNxbGNvbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwic2VsZWN0IFN1Ym1pdHRpbmdfQXBwbGljYWJsZV9NYW51ZmFjdHVyZXJfb3JfQXBwbGljYWJsZV9HUE9fTmFtZSBhcyBDb21wYW55CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsc3VtKFRvdGFsX0Ftb3VudF9vZl9QYXltZW50X1VTRG9sbGFycykgYXMgVG90YWxQYXltZW50cwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbSBjbXNwYXl0YWJsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgYnkgMQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgYnkgMiBkZXNjCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW1pdCAxMCIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyNoYXMgdG9wIGNvbXBhbnkgYnkgcmV2ZW51ZQpkYldyaXRlVGFibGUoY29ubiA9IHJzcWxjb24KICAgICAgICAgICAgICwidG9wY29tcGFueXRhYmxlIgogICAgICAgICAgICAgLHRvcENvbXBhbnkKICAgICAgICAgICAgICxvdmVyd3JpdGUgPSBUUlVFKQpwcmludCh0b3BDb21wYW55KQpgYGAKCgoKQ3JlYXRlIGEgZGF0YXNldCB3aXRoIGNvbXBhbnksIHBheW1lbnQgc3BlY2lhbHR5LCBhbmQgdG90YWwgcGF5bWVudHMuIEdyb3VwIGJ5IHRoZSBhdHRyaWJ1dGVzIGFuZCBzdW0gdGhlIG1lYXN1cmVzLgpUaGVuIGdldCB0aGUgdG9wIGNvbXBhbmllcyB3aXRoIHNwZWNpYWx0eSBvbmx5IGlmIHRoZXkgZXhpc3QgaW4gdGhlIHRvcCAxMCBjb21wYW5pZXMgZGF0YSBmcmFtZS4KCgpgYGB7ciB0b3BzcGVjaWFsdHksIGVjaG89IFRSVUUsIGluY2x1ZGU9IFRSVUV9CnRvcHNwZWNpYWx0eSA8LSBSU1FMaXRlOjpkYkdldFF1ZXJ5KGNvbm4gPSByc3FsY29uCiAgICAgICAgICAgICAgICAgICAgLCAic2VsZWN0IGMuU3VibWl0dGluZ19BcHBsaWNhYmxlX01hbnVmYWN0dXJlcl9vcl9BcHBsaWNhYmxlX0dQT19OYW1lIGFzIENvbXBhbnkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYy5QaHlzaWNpYW5fU3BlY2lhbHR5CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLHN1bShjLlRvdGFsX0Ftb3VudF9vZl9QYXltZW50X1VTRG9sbGFycykgYXMgVG90YWxQYXltZW50cwogICAgICAgICAgICAgICAgICAgICAgIGZyb20gY21zcGF5dGFibGUgYXMgYyBpbm5lciBqb2luIChzZWxlY3QgZGlzdGluY3QgQ29tcGFueQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tIHRvcGNvbXBhbnl0YWJsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciBieSB0b3Bjb21wYW55dGFibGUuVG90YWxQYXltZW50cyBkZXNjCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbWl0IDUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSBhcyB0dCBvbiBjLlN1Ym1pdHRpbmdfQXBwbGljYWJsZV9NYW51ZmFjdHVyZXJfb3JfQXBwbGljYWJsZV9HUE9fTmFtZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IHR0LkNvbXBhbnkKICAgICAgICAgICAgICAgICAgICAgICBncm91cCBieSAxLDIKICAgICAgICAgICAgICAgICAgICAgICBvcmRlciBieSAzIGRlc2MsMiwxCiAgICAgICAgICAgICAgICAgICAgIikKdG9wc3BlY2lhbHR5JFBoeXNpY2lhbl9TcGVjaWFsdHkgPC0gd2l0aGluKHRvcHNwZWNpYWx0eSwgWCA8LSBpZmVsc2UobmNoYXIodG9wc3BlY2lhbHR5JFBoeXNpY2lhbl9TcGVjaWFsdHkpID09ICIwIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCAiTkEiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsdG9wc3BlY2lhbHR5JFBoeXNpY2lhbl9TcGVjaWFsdHkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgIApwcmludCh0b3BzcGVjaWFsdHkpCmBgYAoKIyMgVmlzdWFsaXplCjEuIFRvcCAxMCBjb21wYW5pZXMgYmFyY2hhcnQKMi4gVG9wIDUgY29tcGFuaWVzCgoKYGBge3IgdmlzdWFsaXplLGluY2x1ZGU9VFJVRSwgZWNobz1UUlVFfQoKI3Bsb3RfbHkoeCA9IGModG9wQ29tcGFueSRDb21wYW55KQojICAgICAgICx5ID0gYyh0b3BDb21wYW55JFRvdGFsUGF5bWVudHMpCiMgICAgICAgLHR5cGUgPSAiYmFyIikKI3BhcihtZnJvdyAtIGMoMiwyKSkKZyA8LSBnZ3Bsb3QodG9wQ29tcGFueSxhZXMoQ29tcGFueSxUb3RhbFBheW1lbnRzLzEwMDAwMDApKQpnK2dlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiCiAgICAgICAgICAgLGNvbG91ciA9ICJkYXJrIGJsdWUiCiAgICAgICAgICAgLGZpbGwgPSAiZG9kZ2VyIGJsdWUiKSArdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxoanVzdCA9IDEpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkrIGxhYnMoeSA9ICJUb3RhbCBQYXltZW50cyIpK2dlb21fbGluZSgpKwogICAgICAgICAgICAgICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbWVhbih0b3BDb21wYW55JFRvdGFsUGF5bWVudHMvMTAwMDAwMCksIGNvbG9yPSJibHVlIikKYGBgCgpgYGB7ciB0b3BzcGVjaWFsdHlzdW1tYXJ5LCBlY2hvPVRSVUUsaW5jbHVkZT1UUlVFfQpzdW1tYQpgYGAKCgpgYGB7ciB2aXN1YWxpemVzcGVjaWFsdHlfY29weSwgZWNobz1GQUxTRSxpbmNsdWRlPUZBTFNFfQojcGxvdF9seSh4ID0gYyh0b3BDb21wYW55JENvbXBhbnkpCiMgICAgICAgLHkgPSBjKHRvcENvbXBhbnkkVG90YWxQYXltZW50cykKIyAgICAgICAsdHlwZSA9ICJiYXIiKQojcGFyKG1mcm93IC0gYygyLDIpKQp0cyA8LSBhZ2dyZWdhdGUoVG90YWxQYXltZW50c35QaHlzaWNpYW5fU3BlY2lhbHR5LHRvcHNwZWNpYWx0eSxzdW0pCgoKYiA8LSBnZ3Bsb3QodG9wc3BlY2lhbHR5LGFlcyhDb21wYW55LFRvdGFsUGF5bWVudHMvMTAwMDAwMAogICAgICAgICAgICAgICAgICAgICAgICAgICAsZmlsbCA9IHJlcCh1bmxpc3QoUGh5c2ljaWFuX1NwZWNpYWx0eSkpKQogICAgICAgICAgICApCgpiK2dlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiCiAgICAgICAgICAgLGNvbG91ciA9ICJkYXJrIGJsdWUiCiAgICAgICAgICAgLGZpbGwgPSAiZG9kZ2VyIGJsdWUiKSArdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxoanVzdCA9IDEpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkrIGxhYnMoeSA9ICJUb3RhbCBQYXltZW50cyIpCmBgYAoKYGBge3IgdHJlZW1hcCwgZWNobz1UUlVFLGluY2x1ZGU9VFJVRX0KCiMjIyB1c2UgcGluZyB0byBwcm9kdWNlIGltYWdlIGFuZCBjb250cm9sIHNpemUuCnNwZWNpYWx0eXRyZWUgPC0gZmlsZS5wYXRoKGdldHdkKCkscGFzdGUoInNwZWNpYWx0eXRyZWVtYXAiLCIucG5nIixzZXAgPSAiIikpCnBuZyhmaWxlbmFtZSA9IHNwZWNpYWx0eXRyZWUsCiAgICB3aWR0aCA9IDEwMDAsIGhlaWdodCA9IDg1MCwgdW5pdHMgPSAicHgiLCBwb2ludHNpemUgPSAxMiwKICAgIGJnID0gIndoaXRlIiwgIHJlcyA9IE5BLCMjIC4uLiwKICAgICMjdHlwZSA9IGMoImNhaXJvIiwgImNhaXJvLXBuZyIsICJYbGliIiwgInF1YXJ0eiIpLCAKICAgIGFudGlhbGlhcyA9IGMoImRlZmF1bHQiKQopCgoKCnRyZWVtYXA6OnRyZWVtYXAoZHRmID0gdG9wc3BlY2lhbHR5LCBpbmRleCA9IGMoIkNvbXBhbnkiLCJQaHlzaWNpYW5fU3BlY2lhbHR5IikKICAgICAgICAgICAgICAgICAsdHlwZSA9ICJpbmRleCIKICAgICAgICAgICAgICAgICAsIGZvbnRzaXplLmxhYmVscz1jKDEyLDEwLDEwKQogICAgICAgICAgICAgICAgICx2U2l6ZSA9ICJUb3RhbFBheW1lbnRzIgogICAgICAgICAgICAgICAgICx2Q29sb3IgPSAiUGh5c2ljaWFuX1NwZWNpYWx0eSIKICAgICAgICAgICAgICAgICAsY29tbWFuZC5saW5lLm91dHB1dCA9IEZBTFNFCiAgICAgICAgICAgICAgICAgIyxmb250ZmFjZS5sYWJlbHMgPSAiYm9sZCIKICAgICAgICAgICAgICAgICAscGFsZXR0ZSA9ICJTZXQxIgogICAgICAgICAgICAgICAgICxmdW4uYWdncmVnYXRlID0gInN1bSIKICAgICAgICAgICAgICAgICAsIGFsaWduLmxhYmVscz1saXN0KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoImNlbnRlciIsICJjZW50ZXIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiY2VudGVyIiwgImJvdHRvbSIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICApCmRldi5vZmYoKQpgYGAKCiFbU3BlY2lhbHR5IFRyZWUgTWFwXShzcGVjaWFsdHl0cmVlbWFwLnBuZykKCgoKCgoKCgo=